﻿using System;
using System.Collections.Generic;
using System.Linq;
using Tyche.Common.ProxyBuilder;

namespace Tyche.Common.Resource
{
    public class TycheResourceManager
    {
        /// <summary>
        /// 资源字典
        /// </summary>
        private static Dictionary<Type, TycheResource> resources;

        /// <summary>
        /// 资源字典
        /// </summary>
        private static Dictionary<string, TycheResource> resourceMap;

        /// <summary>
        /// 静态构造函数
        /// </summary>
        static TycheResourceManager()
        {
            resources = new Dictionary<Type, TycheResource>();
            resourceMap = new Dictionary<string, TycheResource>();
        }

        /// <summary>
        /// 创建实例
        /// </summary>
        /// <param name="type"></param>
        /// <param name="isProxy"></param>
        /// <returns></returns>
        public static object CreateInstance(Type type, bool isProxy)
        {
            if (!type.IsInterface || !resources.ContainsKey(type))
            {
                throw new Exception(string.Format("TycheResourceManager找不到{0}的资源", type.FullName));
            }

            if (isProxy)
            {
                return Activator.CreateInstance(resources[type].Proxy
                    , resources[type].Proxy.GetConstructors().First().GetParameters().Select(p => { return CreateInstance(p.ParameterType, true); }).ToArray());
            }
            else
            {
                return Activator.CreateInstance(resources[type].Implement
                    , resources[type].Implement.GetConstructors().First().GetParameters().Select(p => { return CreateInstance(p.ParameterType, true); }).ToArray());
            }
        }

        /// <summary>
        /// 创建实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="isProxy"></param>
        /// <returns></returns>
        public static T CreateInstance<T>(bool isProxy = true)
        {
            return (T)CreateInstance(typeof(T), isProxy);
        }

        /// <summary>
        /// 设置资源
        /// </summary>
        /// <param name="name"></param>
        /// <param name="interfaceType"></param>
        /// <param name="implementType"></param>
        /// <param name="proxyType"></param>
        /// <param name="builder"></param>
        public static void SetResource(string name, Type interfaceType, Type implementType, Type proxyType, ITycheProxyBuilder builder = null)
        {
            if (implementType != null && !implementType.GetInterfaces().Any(i => i == interfaceType))
            {
                throw new Exception("设置TycheResource失败, implementType必须是interfaceType的实现类");
            }

            var resource = new TycheResource
            {
                Name = name,
                Interface = interfaceType,
                Implement = implementType,
                Builder = builder
            };

            if (!string.IsNullOrEmpty(name) && !resourceMap.ContainsKey(name))
            {
                resourceMap[name] = resource;
            }

            if (!resources.ContainsKey(interfaceType))
            {
                resources.Add(interfaceType, resource);
            }
        }

        /// <summary>
        /// 设置资源
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <param name="builder"></param>
        public static void SetResource<T1, T2>(ITycheProxyBuilder builder = null) where T2 : T1
        {
            SetResource(null, typeof(T1), typeof(T2), null, builder);
        }

        /// <summary>
        /// 设置资源
        /// </summary>
        /// <param name="interfaceType"></param>
        /// <param name="builder"></param>
        public static void SetResource(Type interfaceType, ITycheProxyBuilder builder = null)
        {
            SetResource(null, interfaceType, null, null, builder);
        }

        /// <summary>
        /// 获取资源
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static TycheResource GetResource<T>()
        {
            return GetResource(typeof(T));
        }

        /// <summary>
        /// 获取资源
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static TycheResource GetResource(Type type)
        {
            if (!resources.ContainsKey(type))
            {
                throw new Exception(string.Format("无法找到{0}的资源", type.FullName));
            }

            return resources[type];
        }

        /// <summary>
        /// 获取资源
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static TycheResource GetResource(string name)
        {
            if (!resourceMap.ContainsKey(name))
            {
                throw new Exception(string.Format("无法找到{0}的资源", name));
            }

            return resourceMap[name];
        }

        /// <summary>
        /// 获取所有资源
        /// </summary>
        /// <returns></returns>
        public static List<TycheResource> GetResources()
        {
            return resources.Values.ToList();
        }
    }
}
